﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using HtmlAgilityPack;
using System.IO;

/// <summary>
/// Summary description for GameScraper
/// </summary>
public class GameScraper
{

    const string scoresURL = "http://www.nfl.com/scores/";
    const string liveInfoURL = "http://m.nfl.com/scores/";

    public static List<Game> UpdateGames(Week week)
    {   
        List<Game> games = new List<Game>();
        if (week != null)
        {
            games = week.GetGames;

            int compareStartDate = DateTime.Now.CompareTo(((DateTime)week.StartDate));
            int compareEndDate = DateTime.Now.CompareTo(((DateTime)week.StopDate).AddDays(1));
            if (compareStartDate > -1 && compareEndDate < 1)
            {
                var gamesToUpdate = (from g in games
                                     where ((DateTime.Now.CompareTo(((DateTime)g.Date).AddHours(-3)) > 0) && g.GameState != Game.State.PostGame)
                                     select g);
                if (gamesToUpdate.Count() > 0)
                    UpdateGames(games, week);
            }
        }
        return games;
    }

    private static void UpdateGames(IEnumerable<Game> games, Week week)
    {
        HtmlDocument doc = GetHTMLFromNFL(week);
        HtmlDocument livedoc = GetLiveHTMLFromNFL(week);

        foreach (Game game in games)
        {
                bool changes = false;
                string AwayScore;
                string HomeScore;
                string timeLeft;
                AwayScore = doc.DocumentNode.SelectSingleNode(string.Format("//div [@class='team-data']/div [@class='team-info']/p/a [.='{0}']/../../../p [@class='total-score'] ", game.AwayTeam.TeamName)).InnerHtml;
                HomeScore = doc.DocumentNode.SelectSingleNode(string.Format("//div [@class='team-data']/div [@class='team-info']/p/a [.='{0}']/../../../p [@class='total-score'] ", game.HomeTeam.TeamName)).InnerHtml;
                timeLeft = doc.DocumentNode.SelectSingleNode(string.Format("//div [@class='team-data']/div [@class='team-info']/p/a [.='{0}']/../../../../../../div[@class='game-center-area']/p/span [@class='time-left'] ", game.AwayTeam.TeamName)).InnerHtml;
                

                if (timeLeft.Contains("#"))
                {
                    var awayScoreNode = livedoc.DocumentNode.SelectSingleNode(string.Format("//span/em/span[contains(.,'{0}')]/../../b ", game.AwayTeam.TeamName));
                    var homeScoreNode = livedoc.DocumentNode.SelectSingleNode(string.Format("//span/em/span[contains(.,'{0}')]/../../b ", game.HomeTeam.TeamName));


                    var gameDet = livedoc.DocumentNode.SelectSingleNode(string.Format("//span/em/span [contains(.,'{0}')]/../../../span [@class='time'] ", game.AwayTeam.TeamName));

                    if (gameDet != null)
                    {
                        game.GameDetail = gameDet.InnerHtml;
                        game.GameDetail = game.GameDetail = game.GameDetail.Replace("\t", "");
                        game.GameDetail = game.GameDetail.Replace("\n", "");
                        game.GameDetail = game.GameDetail.Replace("</em>", "<br/>");
                        game.GameDetail = game.GameDetail.Replace("<em class=\"down\">", "");
                    }
                    if(awayScoreNode != null)
                        AwayScore = awayScoreNode.InnerHtml;

                    if (homeScoreNode != null)
                        HomeScore = homeScoreNode.InnerHtml;


                    //string homeTeamPOS = livedoc.DocumentNode.SelectSingleNode(string.Format("//span/em/span[contains(.,'{0}')]/../.. ", game.HomeTeam.TeamName)).Attributes[0].Value;
                    //if (homeTeamPOS.Contains("pos"))
                    //    game.HasPossession = game.HomeTeam;
                    //else
                    //    game.HasPossession = game.AwayTeam;
                }
                changes = scoreChanged(game, AwayScore, HomeScore, timeLeft);

                if (changes)
                {
                    
                    DataBase.Games.UpdateGame(game);

                    if (game.GameState == Game.State.PostGame)
                        Helper.ProjectWinner(game.GameWeek);
                }
        }
    }

    const int iEmptyScore = -1;
    private static bool scoreChanged(Game game, string AwayScore, string HomeScore, string timeLeft)
    {
        bool changes = false;

        int newAwayScore = GetScore(game.AwayScore, AwayScore);
        int newHomeScore = GetScore(game.HomeScore, HomeScore);
        if (game.AwayScore != newAwayScore || game.HomeScore != newHomeScore)
        {
            game.AwayScore = newAwayScore;
            game.HomeScore = newHomeScore;
            changes = true;
        }

        if (timeLeft.Contains("ET"))
        {
            if (game.GameState != Game.State.PreGame)
            {
                game.GameState = Game.State.PreGame;
                changes = true;
            }
        }
        else if(timeLeft == FINAL)
        {
            if (game.GameState != Game.State.PostGame)
            {
                if (game.AwayScore > game.HomeScore)
                {
                    game.WinningTeamID = game.AwayTeam.ID;
                    game.LosingTeamID = game.HomeTeam.ID;
                }
                else if (game.AwayScore < game.HomeScore)
                {
                    game.WinningTeamID = game.HomeTeam.ID;
                    game.LosingTeamID = game.AwayTeam.ID;
                }

                changes = true;
                game.GameState = Game.State.PostGame;
                
            }
        }
        else if (game.GameState != Game.State.InGame)
        {
            if (game.GameState != Game.State.InGame)
            {
                game.GameState = Game.State.InGame;
                changes = true;

                new ChatHub().InsertGameStart(string.Format("{0} @ {1} Has Started", game.AwayTeam.TeamName, game.HomeTeam.TeamName), (int)game.GameWeek.ID);


            }
        }

        return changes;
    }

    private static int GetScore(int currentScore, string NewScore)
    {
        if (NewScore == EmptyScore || NewScore.Contains("#"))
            return iEmptyScore;
        else
        {
            int score = int.Parse(NewScore);

            return score;
        }
    }


    public static List<Game> GetGamesForWeek(int number, Season s)
    {
        Week week = DataBase.Weeks.GetWeek(number.ToString(), s);
        if (week == null)
        {
            week = new Week { WeekSeason = s, Number = number, GamesFound = false, StartDate = DateTime.Now, StopDate = DateTime.Now, PostSeason = false};
            DataBase.Weeks.InsertWeek(week);
        }

        List<Game> games = UpdateWeek(week);

        if (week.GamesFound == false && games.Count > 0)
        {
            week.GamesFound = true;

            var tempGames = games.OrderBy(x => x.Date);
            week.StartDate = tempGames.First().Date;
            week.StopDate = tempGames.Last().Date;
             
                DataBase.Weeks.UpdateWeek(week);
        }
        return games;
       
    }

    private static List<Game> UpdateWeek(Week week)
    {
        HtmlDocument doc = GetHTMLFromNFL(week);

         List<Game> games = new List<Game>();

         foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//div [@class='new-score-box-wrapper']"))
            {
                Game game = GetGame(link, week);
                if(game != null)
                    games.Add(game);
            }

         return games;
    }

    private static HtmlDocument GetHTMLFromNFL(Week week)
    {
        string url = null;
        
        if(week.PostSeason)
            url = scoresURL + "POST" + week.Number.ToString();            
        else
            url = scoresURL + week.WeekSeason.StartYear + "/REG" + week.Number.ToString();

        WebRequest req = HttpWebRequest.Create(url);
        req.Method = "GET";

        string source;
        using (StreamReader reader = new StreamReader(req.GetResponse().GetResponseStream()))
        {
            source = reader.ReadToEnd();
        }
        System.Windows.Forms.WebBrowser wb = new System.Windows.Forms.WebBrowser();

        wb.Navigate(url);

        wb.DocumentCompleted += (x,y) {
        
            source = wb.Document.Body.InnerHtml
        };
        //Console.WriteLine(source);
        //WebClient w = new WebClient();
        //string s = w.DownloadString(url);
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(source);
        return doc;
    }

    private static HtmlAgilityPack.HtmlDocument GetLiveHTMLFromNFL(Week week)
    {
        string url = null;
        if(week.PostSeason)
            url = liveInfoURL + "post/" + week.Number.ToString();
        else
            url = liveInfoURL + "reg/" + week.Number.ToString();






        WebClient w = new WebClient();
        string s = w.DownloadString(url);
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(s);
        return doc;
    }

    private static HtmlDocument GetHTMLFromNFLMain()
    {
        WebClient w = new WebClient();
        string s = w.DownloadString("www.nfl.com");
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(s);
        return doc;
    }
    const string EmptyScore = "--";

    private static Game GetGame(HtmlNode link, Week week)
    {

        var teams = link.SelectNodes("./div[@class='new-score-box']//div [@class='team-wrapper']");
        if (teams.Count == 0)
            return null;

        string awayScore;
        Team awayTeam = GetTeam(teams[0],out awayScore);
        string homeScore;
        Team homeTeam = GetTeam(teams[1], out homeScore);

        Game game = DataBase.Games.GetGame(awayTeam, homeTeam, week);
        bool isNew = false;
        string timeLeft = link.SelectSingleNode("./div[@class='new-score-box']/div[@class='game-center-area']/p/span [@class='time-left']").InnerHtml;


        if(game == null)
        {
            isNew = true;
            game = new Game();
            string dateNode = link.SelectSingleNode("./div[@class='new-score-box-heading']//p//span [@class='date']").InnerHtml;
            DateTime date;
            string time = "";
            if (timeLeft.Contains("ET"))
            {
                timeLeft = timeLeft.Replace("ET", "");
                foreach (var s in timeLeft.Split(' '))
                {
                    if (!string.IsNullOrEmpty(s))
                        time += s;
                }
            };
            
            DateTime.TryParse(dateNode.Substring(5) + " " + week.WeekSeason.StartYear + " " + time, out date);

            if (date.Month < 6)
                date.AddYears(1);
             
            game.Date = date;
            game.AwayTeam = awayTeam;
            game.HomeTeam = homeTeam;
            game.GameWeek = week;
            game.GameState = Game.State.PreGame;
            game.AwayScore = -1;
            game.HomeScore = -1;
            
        }
       

        if(game.GameState != Game.State.PostGame)
        {
            bool changesMade = false;


            if (awayScore != EmptyScore)
            {
                 int iAwayScore;
                 if (int.TryParse(awayScore, out iAwayScore))
                 {
                     if (iAwayScore != game.AwayScore)
                     {
                         if (game.GameState == Game.State.PreGame)
                             game.GameState = Game.State.InGame;

                         changesMade = true;
                         game.AwayScore = iAwayScore;
                     }
                 }
            }

            if (homeScore != EmptyScore)
            {
                int iHomeScore;
                if (int.TryParse(homeScore, out iHomeScore))
                {
                    if (iHomeScore != game.HomeScore)
                    {
                        if (game.GameState == Game.State.PreGame)
                            game.GameState = Game.State.InGame;

                        changesMade = true;
                        game.HomeScore = iHomeScore;
                    }
                }
            }


            if (timeLeft == FINAL)
            {

                if (game.AwayScore > game.HomeScore)
                {
                    game.WinningTeamID = game.AwayTeam.ID;
                    game.LosingTeamID = game.HomeTeam.ID;
                }
                else
                {
                    game.WinningTeamID = game.HomeTeam.ID;
                    game.LosingTeamID = game.AwayTeam.ID;
                }

                changesMade = true;
                game.GameState = Game.State.PostGame;

                new ChatHub().InsertGameEnd(string.Format("{0} Beats {1} {2}-{3}", game.WinningTeamID == game.HomeTeam.ID ? game.HomeTeam.TeamName : game.AwayTeam.TeamName, 
                    game.LosingTeamID == game.HomeTeam.ID ? game.HomeTeam.TeamName : game.AwayTeam.TeamName, 
                    game.WinningTeamID == game.HomeTeam.ID ? game.HomeScore : game.AwayScore, 
                    game.WinningTeamID == game.AwayTeam.ID ? game.HomeTeam.TeamName : game.AwayTeam.TeamName), (int)game.GameWeek.ID);

            }

            if (isNew)
                DataBase.Games.InsertGame(game);
            else if (changesMade)
                DataBase.Games.UpdateGame(game);
        }

        return game;
    }



    const string FINAL = "FINAL";
    private static Team GetTeam(HtmlNode teamNode, out string score)
    {
        HtmlNodeCollection col = new HtmlNodeCollection(teamNode);

        HtmlNode info = teamNode.SelectSingleNode(".//div [@class='team-data']");
         HtmlNode name = info.SelectSingleNode(".//p [@class='team-name']");
         HtmlNode scoreNode = info.SelectSingleNode(".//p [@class='total-score']");
         score = scoreNode.InnerHtml;
         string teamName = name.InnerText;
         Team team = DataBase.Teams.GetTeam(teamName);

         if (team == null)
         {
             HtmlNode logoNode = teamNode.SelectSingleNode(".//img [@class='team-logo']");

             team.TeamName = teamName;


             team.IconURL = logoNode.Attributes["src"].Value;
             team.Website = name.FirstChild.Attributes["href"].Value;
             DataBase.Teams.InsertTeam(team);
         }

        
         return team;
    }
}